﻿using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace Miao.SourceGen.Learn
{
    [Generator]
    public class MiaoSourceGeneratorInterface : IIncrementalGenerator
    {
        public static readonly string GeneratorName = "MiaoTest";

        //告诉框架层需要关注哪些文件的变更
        //在有对应的文件的变更情况下，才会触发后续步骤。如此就是增量代码生成的关键
        //告诉框架层从变更的文件里面感兴趣什么数据，对数据预先进行处理
        //预先处理过程中，是会不断进行丢掉处理的
        //其中第一步和第二步可以合在一起
        //使用给出的数据进行处理源代码生成逻辑
        //这一步的逻辑和普通的 Source Generator 是相同的，只是输入的参数不同

        public void Initialize(IncrementalGeneratorInitializationContext context)
        {
            //Debugger.Launch();//牛逼，加这个代码效果把断点打进去了，原生的Unity再编译。////




            //获取筛选（candidate）到的Class上下文
            IncrementalValuesProvider<ClassDeclarationSyntax> candidateProvider = context.SyntaxProvider.CreateSyntaxProvider(
                predicate: MiaoSyntaxFinder.IsSyntaxTargetForGeneration,
                transform: MiaoSyntaxFinder.GetSemanticTargetForGeneration
                ).Where(t => t is { });//Where将空部分剔除
            //拿到编译源文件
            IncrementalValueProvider<Compilation> compilationProvider = context.CompilationProvider;

            //把筛选器拼在一起，变成了一个奇怪的泛型结构
            var combined = candidateProvider.Combine(compilationProvider);

            //这个的泛型还是比较复杂的
            context.RegisterSourceOutput(combined, (productionContext, sourceProviderTuple) =>
            {
                var (classDeclarationSyntax, compilation) = sourceProviderTuple;


                Execute(productionContext, classDeclarationSyntax, compilation);
            });


            //context.RegisterSourceOutput(candidateProvider, Execute);
            // IncrementalValueProvider<Compilation> compilations =
            //context.CompilationProvider
            //    // 这里的 Select 是仿照 Linq 写的，可不是真的 Linq 哦，只是一个叫 Select 的方法
            //    // public static IncrementalValueProvider<TResult> Select<TSource,TResult>(this IncrementalValueProvider<TSource> source, Func<TSource,CancellationToken,TResult> selector)
            //    .Select((compilation, cancellationToken) => compilation);

            //这里第一个参数是判断文件是否是业务逻辑感兴趣的，过滤是否是感兴趣的
            //第二个参数就是转换处理逻辑，要求返回值是处理完成返回的任意类型
            //predicate = 一个函数，用于确定是否应转换给定的<see cref=“SyntaxNode”
            //<param name=“transform”>当<paramref name=“predice”/>为给定节点返回<c>true</c>时执行转换的函数

            //var candidateProvider =  context.SyntaxProvider.CreateSyntaxProvider(
            //    predicate: MySyntaxFinder.IsSyntaxTargetForGeneration,
            //    transform);
        }
        //这个代码如果要时候没有成功生成，也可能是需要重启Unity来使用。
        public static void Execute(SourceProductionContext sourceProductionContext, ClassDeclarationSyntax classDeclarationSyntax, Compilation compilation)
        {
            

            //Debugger.Launch();
            SyntaxTree syntaxTree = classDeclarationSyntax.SyntaxTree;
            SourceText outputSource = MyGenerate.GenerateSourceText();


            string sourceFilePath = SourceOutputHelpers.GetGeneratedSourceFilePath(syntaxTree, compilation.Assembly.Name, "");

            string addSourceName = syntaxTree.GetGeneratedSourceFileName();


            //sourceProductionContext.AddSource("GeneratedSourceTest", outputSource);
            sourceProductionContext.AddSource(addSourceName, outputSource);
            //SourceOutputHelpers.OutputSourceToFile(sourceFilePath, outputSource.ToString());
        }


    }
}